/**
 * @description 流星
 */
class Metro {
  x: number;
  y: number;
  length: number; //长度
  angle: number;  //倾斜角度
  width: number;  //宽度
  height: number; //高度
  speed: number; //速度
  offset_x: number; //横轴移动偏移量
  offset_y: number; //纵轴移动偏移量
  alpha: number; //透明度
  color0: string; //流星的色彩
  color1: string; //流星的色彩
  color2: string; //流星的色彩
  canvasEl: HTMLCanvasElement;
  canvasContext: CanvasRenderingContext2D | null;

  constructor(canvasEl: HTMLCanvasElement, canvasContext: CanvasRenderingContext2D | null){
    this.x = -1
    this.y = -1
    this.length = -1
    this.angle = 30
    this.width = -1
    this.height = -1
    this.speed = 1
    this.offset_x = -1
    this.offset_y = -1
    this.alpha = 1
    this.color0 = ''
    this.color1 = ''
    this.color2 = ''
    this.canvasEl = canvasEl
    this.canvasContext = canvasContext
  }

  /**
   * @description 设置初始流星位置
   */
  setCurrentPosition(){
    this.x = Math.random() * this.canvasEl.width
    this.y = Math.random() * 80
  }

  /**
   * @description 步增流星位置
  */
  countPos(){
    this.x = this.x - this.offset_x
    this.y = this.y + this.offset_y
    // console.log(this.x, this.canvasEl.width, this.alpha,'----this.x')
    if(this.x > this.canvasEl.width + 100 || this.y > this.canvasEl.height + 100 ){
      return true
    }
    return false
  }

  /**
   * @description
   */
  getRandomColor() {
    this.color0 = ['yellow', 'red', 'blue'][(Math.floor(Math.random() * 3))]
    const a = Math.ceil(255 - 240 * Math.random())
    //中段颜色
    this.color1 = 'rgba(' + a + ',' + a + ',' + a + ',1)'
    //结束颜色
    this.color2 = '#05103a'
  }

  /**
   * @description 流星初始化
   */
  init (){
    this.setCurrentPosition()
    this.alpha = 1//透明度
    this.getRandomColor()
    //最小长度，最大长度
    let x = Math.random() * 20 + 30
    this.length = Math.ceil(x)
    //         x = Math.random()*10+30;
    this.angle = 60 //流星倾斜角
    x = Math.random() + 4
    this.speed = Math.ceil(x) //流星的速度
    const cos = Math.cos(this.angle * 3.14 / 180)
    const sin = Math.sin(this.angle * 3.14 / 180)
    this.width = this.length * cos //流星所占宽度
    this.height = this.length * sin//流星所占高度
    this.offset_x = this.speed * cos
    this.offset_y = this.speed * sin
  }

  /**
   * @description 绘制流星
   */
  draw(){
    if(!this.canvasContext){
      return
    }
    this.canvasContext.save()
    this.canvasContext.beginPath()
    this.canvasContext.lineWidth = 1 //宽度
    this.canvasContext.globalAlpha = this.alpha //设置透明度
    //创建横向渐变颜色,起点坐标至终点坐标

    const line = this.canvasContext.createLinearGradient(
      this.x, this.y,
      this.x + this.width,
      this.y - this.height
    )

    //分段设置颜色
    line.addColorStop(0, this.color0)
    line.addColorStop(0.8, this.color1)
    line.addColorStop(0.9, this.color2)
    this.canvasContext.strokeStyle = line
    //起点
    this.canvasContext.moveTo(this.x, this.y)
    //终点
    this.canvasContext.lineTo(this.x + this.width, this.y - this.height)
    this.canvasContext.closePath()
    this.canvasContext.stroke()
    this.canvasContext.restore()
  }

  /**
   * @description 流星移动
   */
  move() {
    //清空流星像素
    if(!this.canvasContext){
      return
    }
    const x = this.x + this.width - this.offset_x
    const y = this.y - this.height
    this.canvasContext.clearRect(x - 3, y - 3, this.offset_x + 5, this.offset_y + 5)
    let isOutBound = this.countPos()
    // console.log(isOutBound, '----isOutBound');
    this.alpha -= 0.02
    if(this.alpha <= 0){
      isOutBound = true
    }
    if(isOutBound){
      return true
    }
    this.draw()
    return false
  }

  clear(){
    if(!this.canvasContext){
      return
    }
    const x = this.x + this.width - this.offset_x
    const y = this.y - this.height
    // console.log(this.x, this.y)
    // 所以每次只能绘制一个流星
    this.canvasContext.clearRect(0, 0, this.canvasEl.width , this.canvasEl.height )
  }

}

/**
 * @description 流星活动容器
 */
class MetroPanel {
  context: CanvasRenderingContext2D | null;
  canvasEl: HTMLCanvasElement;
  constructor(el: HTMLElement){
    const canvasEl = document.createElement('canvas')
    el.appendChild(canvasEl)
    el.offsetWidth
    canvasEl.width = el.offsetWidth
    canvasEl.height = el.offsetHeight
    this.context = canvasEl.getContext('2d')
    this.canvasEl = canvasEl
  }

  addMetro(){
    //let metro = null;
    let metro: any = new Metro(this.canvasEl, this.context) || null
    metro.init()
    const interval = setInterval(()=> {
      const isOutBound = metro.move()
      if(isOutBound){
        clearInterval(interval)
        metro.clear()
        metro = null
      }
    }, 20)
  }
}

const metroDirective = {

  mounted(el: HTMLElement){
    const metroPanel = new MetroPanel(el)
    metroPanel.addMetro()
    let count = 0
    const step = () => {
      count++
      if(count === 200){
        count = 0
        metroPanel.addMetro()
      }
      window.requestAnimationFrame(step)
    }

    if(window.requestAnimationFrame){
      window.requestAnimationFrame(step)
    }
  }
}

/**
 * @description 安装为全局指令
 */
export default {

  install(app: any){
    app.directive('metro', metroDirective)
  }

}
